PLUGIN.Name = "Super DoF : Constant Focus"
PLUGIN.DefaultOn = false
PLUGIN.Description = "Allows you to use Super DoF while playing (Use with Source Recorder for Machinima purposes)."
PLUGIN.Trigger = false


function PLUGIN:LoadParameters()
	self:AddParameter("rendermode", { Type = "checkbox", Defaults = "0", Text = "Render Mode" } )
	self:AddParameter("blursize", { Type = "slider", Defaults = "5", Min = "0", Max = "10", Decimals = "3", Text = "Blur Size" } )
	self:AddParameter("distance", { Type = "slider", Defaults = "128", Min = "4", Max = "4096", Decimals = "0", Text = "Focus Distance" } )

	self:AddParameter("rm_radial", { Type = "slider", Defaults = "16", Min = "16", Max = "32", Decimals = "0", Text = "Render Mode : Radial Steps" } )
	self:AddParameter("rm_passes", { Type = "slider", Defaults = "6", Min = "6", Max = "12", Decimals = "0", Text = "Render Mode : Passes" } )
	
end

function PLUGIN:Load()
	self.texFSB = render.GetSuperFPTex()
	self.matFSB = Material( "pp/motionblur" )
	self.matFB	 = Material( "pp/fb" )
end

function PLUGIN:Unload()
end

function PLUGIN:_RenderDoF( vOrigin, vAngle, vFocus, fAngleSize, radial_steps, passes, drawhud, bSpin )

	local OldRT 	= render.GetRenderTarget();
	local view 		= {  x = 0, y = 0, w = ScrW(), h = ScrH(), drawhud = drawhud }
	local fDistance = vOrigin:Distance( vFocus )
	
	fAngleSize = fAngleSize * math.Clamp( 256/fDistance, 0.1, 1 ) * 0.5
	
	view.origin = vOrigin
	view.angles = vAngle
	
	// Straight render (to act as a canvas)
	render.RenderView( view )
	render.UpdateScreenEffectTexture()
	
	render.SetRenderTarget( self.texFSB )
			self.matFB:SetMaterialFloat( "$alpha", 1  )
			render.SetMaterial( self.matFB )
			render.DrawScreenQuad()	
	
	local Radials = (math.pi*2) / radial_steps
	
	for mul=(1 / passes), 1, (1 / passes) do
	
		for i=0,(math.pi*2), Radials do
		
			local VA = vAngle * 1 // hack - this makes it copy the angles instead of the reference
			
			// Rotate around the focus point
			VA:RotateAroundAxis( vAngle:Right(), 	math.sin( i + (mul) ) * fAngleSize * mul )
			VA:RotateAroundAxis( vAngle:Up(), 		math.cos( i + (mul) ) * fAngleSize * mul )
			
			ViewOrigin = vFocus - VA:Forward() * fDistance
			
			view.origin = ViewOrigin
			view.angles = VA
			
			// Render to the front buffer
			render.SetRenderTarget( OldRT )
			render.Clear( 0, 0, 0, 255, true )
			render.RenderView( view )
			render.UpdateScreenEffectTexture()
			
			// Copy it to our floating point buffer at a reduced alpha
			render.SetRenderTarget( self.texFSB )
			local alpha = (Radials/(math.pi*2)) 		// Divide alpha by number of radials
			alpha = alpha * (1-mul)					// Reduce alpha the further away from center we are
			self.matFB:SetMaterialFloat( "$alpha", alpha  )
			

				render.SetMaterial( self.matFB )
				render.DrawScreenQuad()

			// We have to SPIN here to stop the Source engine running out of render queue space.
			if ( bSpin ) then
			
				// Restore RT
				render.SetRenderTarget( OldRT )
	
				// Render our result buffer to the screen
				self.matFSB:SetMaterialFloat( "$alpha", 1 )
				self.matFSB:SetMaterialTexture( "$basetexture", self.texFSB )
		
				render.SetMaterial( self.matFSB )
				render.DrawScreenQuad()
			
				render.Spin()
				
			end
		
		end
		
	end
	
	// Restore RT
	render.SetRenderTarget( OldRT )
	
	// Render our result buffer to the screen
	--self.matFSB:SetMaterialFloat( "$alpha", 1 )
	--self.matFSB:SetMaterialTexture( "$basetexture", self.texFSB )
		
	--render.SetMaterial( self.matFSB )
	--render.DrawScreenQuad()

end

function PLUGIN:_RenderSuperDoF( ViewOrigin, ViewAngles )

	local FocusPoint = ViewOrigin + ViewAngles:Forward() * self:GetNumber("distance")
	local userender = self:GetNumber("rendermode") > 0

	self:_RenderDoF( ViewOrigin, ViewAngles, FocusPoint, self:GetNumber("blursize"), userender and self:GetNumber("rm_radial") or 2, userender and self:GetNumber("rm_passes") or 4, 1, userender )
	
	self.matFSB:SetMaterialFloat( "$alpha", 1 )
	self.matFSB:SetMaterialTexture( "$basetexture", self.texFSB )
	render.SetMaterial( self.matFSB )
	render.DrawScreenQuad()
	
end

function PLUGIN.HOOK:RenderScene( ViewOrigin, ViewAngles )

	if ( FrameTime() == 0 ) then return end -- If console is up, don't render
	
	self:_RenderSuperDoF( ViewOrigin, ViewAngles )
	return true

end
